home *** CD-ROM | disk | FTP | other *** search
/ Microsoft Multimedia Viewer How-To CD / Microsoft Multimedia Viewer How-To CD.iso / mvsample / progsamp / eplist / eplist.c next >
C/C++ Source or Header  |  1993-03-21  |  25KB  |  907 lines

  1. #include <windows.h>
  2. #include <windowsx.h>
  3. #include <mmsystem.h>
  4. #include <stdlib.h>
  5. #include <viewer.h>
  6.  
  7. #include "EPLIST.h"
  8. #include "scrolwin.h"
  9. #include "mvbtask.h"
  10. #include "graphics.h"
  11. #include "parse.h"
  12.  
  13. #define BORDER_WIDTH 8
  14. #define BEVEL_WIDTH  3
  15.  
  16. HANDLE      ghModule;   // Our Module handle
  17.  
  18. char szEPClassName[] = "ListPane";
  19. char szScrollClassName[] = "EPScrollWin";
  20.  
  21. /************************************************************************
  22.  * ShowMessage
  23.  *
  24.  * Load a string resource and display in a message box.
  25.  *
  26.  ************************************************************************/
  27.  
  28. void ShowMessage(
  29.     HWND hWnd,              // Parent window for message box
  30.     int nMessage,           // String resource ID for message
  31.     int nIcon)              // Type of icon to display
  32. {
  33.     char szMessage[512];
  34.  
  35.     MessageBeep(nIcon);
  36.  
  37.     if(LoadString(ghModule, nMessage, szMessage, 511) > 0)
  38.     {
  39.         MessageBox(hWnd, szMessage, szEPClassName, 
  40.                     MB_OK | nIcon);
  41.     }
  42.     else
  43.     {
  44.         MessageBox(hWnd, "Unspecified error.", szEPClassName, 
  45.                     MB_OK | nIcon);
  46.     }
  47. }
  48.  
  49.  
  50. /************************************************************************
  51.  * LibMain
  52.  *          
  53.  * Initialization function for the DLL
  54.  *          
  55.  * - Registers the two window classes used for the embedded pane
  56.  * - Initializes the task table
  57.  *
  58.  * Returns: TRUE if initialization succeeds, FALSE otherwise
  59.  *
  60.  ************************************************************************/
  61.  
  62. BOOL CALLBACK LibMain(HANDLE hModule, int cbHeap, LPSTR lpchCmdLine)
  63. {
  64.     WNDCLASS wc;
  65.  
  66.     ghModule = hModule;
  67.  
  68.     wc.lpszClassName  = szEPClassName;
  69.     wc.style          = CS_GLOBALCLASS;
  70.     wc.hCursor        = LoadCursor(NULL, IDC_ARROW);
  71.     wc.hIcon          = NULL;
  72.     wc.lpszMenuName   = NULL;
  73.     wc.hbrBackground  = COLOR_WINDOW + 1;
  74.     wc.hInstance      = hModule;
  75.     wc.lpfnWndProc    = PaneListProc;
  76.     wc.cbClsExtra     = 0;
  77.     wc.cbWndExtra     = sizeof(LPLISTINFO);
  78.  
  79.     if(!RegisterClass(&wc))
  80.         return FALSE;
  81.  
  82.     wc.style          = CS_DBLCLKS;
  83.     wc.lpszClassName  = szScrollClassName;
  84.     wc.lpfnWndProc    = ScrollWinProc;
  85.  
  86.     if(!RegisterClass(&wc))
  87.         return FALSE;
  88.  
  89.     InitTasks();
  90.  
  91.     return TRUE;
  92. }
  93.  
  94.  
  95.  
  96. /************************************************************************
  97.  * AddLI
  98.  *
  99.  * Adds a list info structure to the task list table
  100.  *
  101.  * Returns: Index of the list entry if successful, -1 otherwise.
  102.  *
  103.  ************************************************************************/
  104.  
  105. int AddLI(
  106.     LPVWRINFO lpVwrInfo,        // Task info for current instance
  107.     LPLISTINFO lpLI)            // To add to list
  108. {                    
  109.     int i;
  110.     
  111.     for(i = 0; i < MAX_WINDOWS && lpVwrInfo->alpLI[i]; i++);
  112.  
  113.     if(i != MAX_WINDOWS)
  114.     {
  115.         lpVwrInfo->alpLI[i] = lpLI;
  116.         return i;
  117.     }
  118.     return -1;
  119. }
  120.  
  121.  
  122. /************************************************************************
  123.  * RemoveLI
  124.  *
  125.  * Deletes a list info structure from the task list table
  126.  *
  127.  ************************************************************************/
  128.  
  129. void RemoveLI(
  130.     LPVWRINFO lpVwrInfo,        // Task info for current instance
  131.     LPLISTINFO  lpLI)           // To remove from list
  132. {
  133.     int i;
  134.     
  135.     for(i = 0; i < MAX_WINDOWS && lpVwrInfo->alpLI[i] != lpLI; i++);
  136.  
  137.     if(i != MAX_WINDOWS)
  138.     {
  139.         lpVwrInfo->alpLI[i] = NULL;
  140.     }
  141. }
  142.  
  143.  
  144. /************************************************************************
  145.  * FreeLI
  146.  *
  147.  * Frees memory used by a list info structure
  148.  *
  149.  ************************************************************************/
  150.  
  151. void FreeLI(
  152.     LPLISTINFO  lpLI)           // To remove from list
  153. {
  154.     if(lpLI->lpszText)
  155.         GlobalFreePtr(lpLI->lpszText);
  156.  
  157.     if(lpLI->hwndScroll)
  158.         DestroyWindow(lpLI->hwndScroll);
  159.  
  160.     if(lpLI->hfontLB)
  161.         DeleteObject(lpLI->hfontLB);
  162.  
  163.     GlobalFreePtr(lpLI);
  164. }
  165.  
  166.  
  167. /************************************************************************
  168.  * FindLI
  169.  *
  170.  * Finds a previously stored list info structure
  171.  *
  172.  * Returns: Handle to list info structure with matching author-data
  173.  *          string. Returns NULL if no such list exists.
  174.  *
  175.  ************************************************************************/
  176.  
  177. LPLISTINFO FindLI(
  178.     LPVWRINFO lpVwrInfo,        // Task info for current instance
  179.     LPSTR     lpszAuthor)       // Author data string to find
  180. {
  181.     int i;
  182.  
  183.     for(i = 0; i < MAX_WINDOWS; i++)
  184.     {
  185.         if(!lpVwrInfo->alpLI[i])
  186.             continue;
  187.  
  188.         if(lstrcmp(lpszAuthor, lpVwrInfo->alpLI[i]->szAuthorData) == 0)
  189.             return lpVwrInfo->alpLI[i];
  190.     }
  191.     return NULL;
  192. }
  193.  
  194.  
  195. /*************************************************************************
  196.  * DoCommand
  197.  *
  198.  * This function submits the selected command to Viewer. To determine
  199.  * which command is selected, it looks at the list info structure passed
  200.  * to lpLI.
  201.  *
  202.  * Returns: Zero if successful; otherwise, returns an error code.
  203.  *
  204.  *************************************************************************/
  205.  
  206. int DoCommand(
  207.     LPVWRINFO lpVwrInfo,        // Viewer instance info (VWR handle)
  208.     LPSTR lpszCommand)          // List info structure
  209. {
  210.     VWR vwrRet;
  211.  
  212.     if(lpVwrInfo == NULL)
  213.         return LISTERR_NOVWRINFO;
  214.  
  215.     if(lpszCommand == NULL)
  216.         return 0;
  217.  
  218.     vwrRet = VwrCommand(lpVwrInfo->vwr, NULL, lpszCommand, cmdoptNONE);
  219.  
  220.     if(vwrRet == lpVwrInfo->vwr)
  221.         return 0;
  222.     else
  223.         return LISTERR_NOVWR;
  224. }
  225.  
  226.  
  227. /*************************************************************************
  228.  * GetPaneSize
  229.  *
  230.  * This function is called in response to the EWM_QUERYSIZE message.
  231.  * It fills the POINT structure pointed to by lpptSize with the x and y
  232.  * extents of the pane. The uses the authored size values for a display
  233.  * pane, but for a printed pane, it must scale the size values to
  234.  * match the resolution of the printer.
  235.  *
  236.  * Returns: TRUE if successful, FALSE otherwise. This return value can
  237.  *          be passed to the EWM_QUERYSIZE return; TRUE means use the
  238.  *          size values pointed to by lpptSize, and FALSE means ignore
  239.  *          the size values.
  240.  * 
  241.  *************************************************************************/
  242.  
  243. BOOL GetPaneSize(
  244.     LPLISTINFO lpLI,            // List info structure
  245.     HDC     hdc,                // HDC for display device
  246.     LPPOINT lpptSize)           // Receives pane dimensions
  247. {
  248.     POINT ptDisp, ptPrt;
  249.     HDC hdcDisplay;
  250.  
  251.     if(lpLI == NULL)
  252.         return FALSE;
  253.  
  254.     lpptSize->x = lpLI->iWidth;
  255.     lpptSize->y = lpLI->iHeight;
  256.  
  257.     // If this is a printer DC, scale the pane appropriately.
  258.  
  259.     if(GetDeviceCaps(hdc, TECHNOLOGY) == DT_RASPRINTER)
  260.     {
  261.         hdcDisplay = CreateIC("DISPLAY", NULL, NULL, NULL);
  262.  
  263.         ptDisp.x = GetDeviceCaps(hdcDisplay, LOGPIXELSX);
  264.         ptDisp.y = GetDeviceCaps(hdcDisplay, LOGPIXELSY);
  265.  
  266.         DeleteDC(hdcDisplay);
  267.  
  268.         ptPrt.x = GetDeviceCaps(hdc, LOGPIXELSX);
  269.         ptPrt.y = GetDeviceCaps(hdc, LOGPIXELSY);
  270.  
  271.         lpptSize->x = lpptSize->x * (ptPrt.x / ptDisp.x);
  272.         lpptSize->y = lpptSize->y * (ptPrt.y / ptDisp.y);
  273.     }
  274.  
  275.     return TRUE;
  276. }
  277.  
  278.  
  279.  
  280. /**************************************************************************
  281.  *
  282.  * PrintPane
  283.  *
  284.  * This function is called in response to the EWM_PRINT message. The
  285.  * function creates a print image of the pane and draws the image to
  286.  * the device and into the rectangle identified by the lpRI parameter.
  287.  * 
  288.  *************************************************************************/
  289.  
  290. void PrintPane(
  291.     LPLISTINFO   lpLI,      // List info structure
  292.     LPRENDERINFO lpRI)      // Identifies print device & print location
  293. {
  294.     RECT  rc;
  295.     HFONT hfont,  hfontOld;
  296.     int   nBevel, nBorder;
  297.  
  298.     if(lpLI == NULL)
  299.         return;
  300.  
  301.     // Need to make a new font for the printer device.
  302.  
  303.     hfont = MakeFont(lpRI->hds, lpLI->szFont, lpLI->iFontSize);
  304.     if(hfont)
  305.     {
  306.         hfontOld = SelectObject(lpRI->hds, hfont);
  307.     }
  308.  
  309.     // Scale the pane border so it's proportional
  310.  
  311.     nBevel = BEVEL_WIDTH*(lpRI->rc.right-lpRI->rc.left)/lpLI->iWidth;
  312.  
  313.     RectBorder(lpRI->hds, &lpRI->rc, nBevel);
  314.  
  315.     CopyRect(&rc, &lpRI->rc);
  316.  
  317.     nBorder = BORDER_WIDTH*(lpRI->rc.right-lpRI->rc.left)/lpLI->iWidth;
  318.  
  319.     rc.left   += nBorder;
  320.     rc.top    += nBorder;
  321.     rc.right  -= nBorder;
  322.     rc.bottom -= nBorder;
  323.  
  324.     Rectangle(lpRI->hds, rc.left, rc.top, rc.right, rc.bottom);
  325.  
  326.     rc.left   += 1;
  327.     rc.top    += 1;  
  328.     rc.right  -= 1;
  329.     rc.bottom -= 1;
  330.  
  331.     DrawList(lpRI->hds, rc.left, rc.top, &rc, lpLI->alpszText, 
  332.                 lpLI->nTop, lpLI->nCurSel, lpLI->nItems);
  333.  
  334.     if(hfont)
  335.     {
  336.         SelectObject(lpRI->hds, hfontOld);
  337.         DeleteObject(hfont);
  338.     }
  339. }
  340.  
  341.  
  342. /*************************************************************************
  343.  * PaneListProc
  344.  *
  345.  * This is the window procedure for the embedded pane. It processes
  346.  * messages for the pane.
  347.  *
  348.  *************************************************************************/
  349.  
  350. LONG CALLBACK PaneListProc(
  351.     HWND   hwnd,                // Window handle of pane
  352.     UINT   msg,                 // Message to process
  353.     WPARAM wParam,              // Message parameter
  354.     LPARAM lParam)              // Message parameter
  355. {
  356.     LPLISTINFO  lpLI;
  357.     LPVWRINFO   lpVwrInfo;
  358.     int         iRet;
  359.  
  360.     switch(msg)
  361.     {
  362.     case WM_CREATE:
  363.     {
  364.         // The pane can be created when the topic is first displayed,
  365.         // when the pane is scrolled into view, or when the topic is
  366.         // printed or copied. Viewer passes an EWDATA structure with
  367.         // the WM_CREATE message; this structure identifies the title
  368.         // and Viewer version and specifies whether the pane is being
  369.         // created for display (default), printing, or copying.
  370.  
  371.         LPCREATESTRUCT lpCreate = (LPCREATESTRUCT)lParam;
  372.         LPEWDATA  lpew = (LPEWDATA)lpCreate->lpCreateParams;
  373.  
  374.         if(lpew == NULL) 
  375.             return -1;
  376.  
  377.         if(lpew->idMajVersion == 0 && lpew->idMinVersion == 0) 
  378.             return -1;
  379.     
  380.         lpVwrInfo = GetTaskData(GetWindowWord(hwnd, GWW_HINSTANCE));
  381.         if(lpVwrInfo == NULL)
  382.         {
  383.             ShowMessage(NULL, LISTERR_NOVWRINFO, MB_ICONEXCLAMATION);
  384.             return -1;
  385.         }
  386.     
  387.         if(lpVwrInfo->szMVB[0] == '\0')
  388.             CopyFilename(lpVwrInfo->szMVB, lpew->szFileName);
  389.  
  390.         // If the pane is being created for copying or printing, first 
  391.         // try to find the matching display version so we can use its
  392.         // list-info structure. This lets us create a print or copy 
  393.         // image that matches the state of the displayed pane
  394.  
  395.         // NOTE: the display version might not exist if the pane was 
  396.         // scrolled off-screen.
  397.  
  398.         lpLI = NULL;
  399.  
  400.         if(lpew->dwFlags & EWF_PRINT || lpew->dwFlags & EWF_COPY)
  401.         {
  402.             lpLI = FindLI(lpVwrInfo, lpew->szAuthorData);
  403.         }
  404.  
  405.         if(lpLI == NULL)
  406.         {
  407.             iRet = InitPane(hwnd, lpew, &lpLI, lpCreate->cx, lpCreate->cy);
  408.             if(iRet)
  409.             {
  410.                 return -1;
  411.             }
  412.             else
  413.             {
  414.                 if(AddLI(lpVwrInfo, lpLI) == -1)
  415.                 {
  416.                     FreeLI(lpLI);
  417.                     ShowMessage(NULL, LISTERR_TOOMANY, MB_ICONEXCLAMATION);
  418.                     return -1;
  419.                 }
  420.             }
  421.         }
  422.  
  423.         // Store the list info with the window
  424.  
  425.         SetWindowLong(hwnd, 0, (LONG)lpLI);
  426.     
  427.         return 0;
  428.     }
  429.  
  430.     case WM_SHOWWINDOW:
  431.  
  432.         // When Viewer makes our pane visible, we can show the scrolling
  433.         // window.
  434.  
  435.         lpLI = (LPLISTINFO)GetWindowLong(hwnd, 0);
  436.         if(lpLI)
  437.         {
  438.             if(hwnd == lpLI->hwndPane && lpLI->hwndScroll)
  439.                 ShowWindow(lpLI->hwndScroll, SW_SHOWNA);
  440.         }
  441.         break;
  442.  
  443.     case WM_DESTROY:
  444.  
  445.         // We can destroy the list information when the pane is destroyed.
  446.         // However, since print/copy panes can share data with the 
  447.         // displayed panes, we must first check to make sure the current
  448.         // window handle (hwnd) matches the one recorded in the pane data
  449.         // structure (lpLI->hwndPane).
  450.         
  451.         lpLI = (LPLISTINFO)GetWindowLong(hwnd, 0);
  452.         if(lpLI && lpLI->hwndPane == hwnd)
  453.         {
  454.             lpVwrInfo = GetTaskData(GetWindowWord(hwnd, GWW_HINSTANCE));
  455.  
  456.             if(lpVwrInfo)
  457.                 RemoveLI(lpVwrInfo, lpLI);
  458.             else
  459.                 ShowMessage(NULL, LISTERR_NOVWRINFO, MB_ICONEXCLAMATION);
  460.  
  461.             FreeLI(lpLI);
  462.         }
  463.  
  464.         break;
  465.  
  466.     case WM_PAINT:
  467.     {
  468.         // This window is only responsible for painting the beveled
  469.         // border.
  470.  
  471.         PAINTSTRUCT ps;
  472.         RECT rc;
  473.  
  474.         BeginPaint( hwnd, &ps );
  475.  
  476.         GetClientRect(hwnd, &rc);
  477.  
  478.         RectBorder(ps.hdc, &rc, BEVEL_WIDTH);
  479.  
  480.         EndPaint( hwnd, &ps );
  481.  
  482.         return 0L;
  483.     }
  484.  
  485.     case WM_USER_LISTDBLCLK:
  486.  
  487.         // This message is posted from the scrolling window when the
  488.         // user double-clicks a list entry.
  489.         
  490.         lpVwrInfo = GetTaskData(GetWindowWord(hwnd, GWW_HINSTANCE));
  491.  
  492.         iRet = DoCommand(lpVwrInfo, (LPSTR)lParam);
  493.         if(iRet)
  494.             ShowMessage(GetParent(hwnd), iRet, MB_ICONEXCLAMATION);
  495.  
  496.         return 0;
  497.  
  498.     case WM_USER_LISTSELECT:
  499.  
  500.         // By responding to this message rather than the above message,
  501.         // the pane could submit commands whenever the selection changed.
  502.  
  503.         return 0;
  504.  
  505.     case EWM_RENDER:
  506.  
  507.         // This message is only received if our EWM_COPY code fails.
  508.  
  509.         return NULL;
  510.  
  511.     case EWM_COPY:
  512.     {
  513.         // When the topic is copied, just provide the currently selected
  514.         // line in the list box. Printing the entire list box would look
  515.         // strange in the copy text.
  516.  
  517.         LPSTR   lpszCopy;
  518.         HANDLE  hCopy;
  519.  
  520.         lpLI = (LPLISTINFO)GetWindowLong(hwnd, 0);
  521.         if(lpLI == NULL)
  522.             return NULL;
  523.  
  524.         lpszCopy = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_SHARE, 
  525.                     lstrlen(lpLI->alpszText[lpLI->nCurSel])+1);
  526.  
  527.         if(lpszCopy)
  528.         {
  529.             lstrcpy(lpszCopy, lpLI->alpszText[lpLI->nCurSel]);
  530.  
  531.             hCopy = GlobalPtrHandle(lpszCopy);
  532.  
  533.             GlobalUnlock(hCopy);
  534.  
  535.             return hCopy;
  536.         }
  537.         else
  538.             return NULL;
  539.     }
  540.  
  541.     case EWM_PRINT:
  542.  
  543.         // Print the pane using the device context supplied with the
  544.         // RENDERINFO structure.
  545.  
  546.         lpLI = (LPLISTINFO)GetWindowLong(hwnd, 0);
  547.  
  548.         PrintPane(lpLI, (LPRENDERINFO)lParam);
  549.  
  550.         return TRUE;
  551.  
  552.     case EWM_QUERYSIZE:
  553.  
  554.         // Provide size values for the pane
  555.  
  556.         lpLI = (LPLISTINFO)GetWindowLong(hwnd, 0);
  557.  
  558.         return GetPaneSize(lpLI, (HDC)wParam, (LPPOINT)lParam);
  559.  
  560.     case EWM_ASKPALETTE:
  561.         return NULL;
  562.     }
  563.     return DefWindowProc(hwnd, msg, wParam, lParam);
  564. }
  565.  
  566.  
  567. /*************************************************************************
  568.  * ReadBaggageFile
  569.  *
  570.  * This function reads the contents of a baggage file into the lpszText
  571.  * buffer. The function just returns the file size if the lpszText
  572.  * parameter is NULL.
  573.  *
  574.  * Returns: count of bytes in file (if lpszText == NULL)
  575.  *          count of bytes read if successful
  576.  *          -1 if an error occurs
  577.  *
  578.  *************************************************************************/
  579.  
  580. long ReadBaggageFile(
  581.     LPSTR lpszMVB,              // Specifies the MVB filename
  582.     LPSTR lpszBagFile,          // Specifies the baggage filename
  583.     LPSTR lpszText,             // To receive baggage file text
  584.     long  lcbMax)               // Max number of characters to copy
  585. {
  586.     char  szPath[_MAX_PATH];
  587.     HMMIO hFile = NULL;
  588.     long  lcBytes = -1;
  589.  
  590.     // Construct a baggage filename and try to open the file.
  591.  
  592.     wsprintf(szPath, "%s+%s", lpszMVB, lpszBagFile);
  593.  
  594.     hFile = mmioOpen(szPath, NULL, MMIO_READ);
  595.     if(hFile == NULL)
  596.     {
  597.         return -1;
  598.     }
  599.  
  600.     // Get file size and return if lpszText is NULL
  601.  
  602.     lcBytes = mmioSeek(hFile, 0, SEEK_END);
  603.     if(lpszText == NULL)
  604.     {
  605.         mmioClose(hFile, 0);
  606.         return lcBytes;
  607.     }
  608.  
  609.     // Read the file contents and close the file
  610.  
  611.     mmioSeek(hFile, 0, SEEK_SET);
  612.  
  613.     if(lcbMax > lcBytes)
  614.         lcBytes = mmioRead(hFile, lpszText, lcBytes);
  615.     else
  616.         lcBytes = mmioRead(hFile, lpszText, lcbMax-1);
  617.  
  618.     mmioClose(hFile, 0);
  619.  
  620.     *(lpszText + lcBytes) = 0;
  621.  
  622.     return lcBytes;
  623. }
  624.  
  625.  
  626. /*************************************************************************
  627.  * ReadCmdList
  628.  *
  629.  * This function reads the list file from baggage and parses the file
  630.  * contents into a series of list entries and associated commands.
  631.  * The function initializes the alpszCommand and alpszText arrays with
  632.  * the starting locations of the list entries. It inserts NULL characters
  633.  * into the buffer to terminate the list entries and commands.
  634.  *
  635.  *************************************************************************/
  636.  
  637. int ReadCmdList(
  638.     LPSTR lpszMVB,              // Name of MVB file
  639.     LPLISTINFO lpLI)            // List information structure
  640. {
  641.     LPSTR lpszTab, lpszText;
  642.     int i;
  643.     long lcBaggage;
  644.  
  645.     // First get the count of bytes in the baggage file
  646.  
  647.     lcBaggage = ReadBaggageFile(lpszMVB, lpLI->szListFilename, NULL, 0);
  648.     if(lcBaggage == -1)
  649.         return LISTERR_BAGGAGE;
  650.  
  651.     // Allocate a buffer and read the contents into memory
  652.  
  653.     lpLI->lpszText = GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, 
  654.                                     lcBaggage +1);
  655.     if(lpLI->lpszText == NULL)
  656.         return LISTERR_MEMORY;
  657.  
  658.     if(ReadBaggageFile(lpszMVB, lpLI->szListFilename, lpLI->lpszText, 
  659.                         lcBaggage+1) == -1)
  660.     {
  661.         GlobalFreePtr(lpLI->lpszText);
  662.         lpLI->lpszText = NULL;
  663.  
  664.         return LISTERR_BAGGAGE;
  665.     }
  666.  
  667.     // Build the topic list.
  668.  
  669.     for(i = 0, lpszText = lpLI->lpszText;
  670.         *lpszText && i < MAX_LIST; 
  671.         lpszText++)
  672.     {
  673.         lpLI->alpszText[i] = lpszText;
  674.  
  675.         for(lpszTab = NULL; *lpszText && *lpszText != '\r'; lpszText++)
  676.         {
  677.             if(*lpszText == '\t')
  678.                 lpszTab = lpszText;
  679.         }
  680.  
  681.         if(lpszTab == NULL)
  682.         {
  683.             lpLI->alpszCommand[i] = NULL;
  684.         }
  685.         else
  686.         {
  687.             *lpszTab = 0;
  688.  
  689.             lpLI->alpszCommand[i] = lpszTab+1;
  690.         }
  691.  
  692.         if(*lpszText == '\r')
  693.             *lpszText++ = 0;
  694.  
  695.         i++;
  696.     }
  697.  
  698.     lpLI->nItems = i;
  699.  
  700.     return 0;
  701. }
  702.  
  703.  
  704. /**************************************************************************
  705.  *
  706.  * InitPaneAspect
  707.  *
  708.  * This function initializes the visual aspects of the pane (size, font,
  709.  * etc.) using the author data in the LISTINFO structure.
  710.  *
  711.  * Returns: Zero if successful; otherwise, returns an error code.
  712.  *
  713.  **************************************************************************/
  714.  
  715. int InitPaneAspect(
  716.     HWND hwnd,              // Window handle of embedded pane
  717.     LPLISTINFO lpLI,        // Info block for embedded pane
  718.     int  cx,                // Default size for pane
  719.     int  cy)
  720. {
  721.     HDC hdc;
  722.     TEXTMETRIC tm;
  723.     HFONT hfontOld;
  724.     int  cxScreen, cyScreen;
  725.     long lx, ly;
  726.  
  727.     // Create a font and get the text metrics.
  728.  
  729.     if(*lpLI->szFont == '\0')
  730.         lstrcpy(lpLI->szFont, "Helv");
  731.  
  732.     if(lpLI->iFontSize == 0)
  733.         lpLI->iFontSize = 8;
  734.  
  735.     hdc = GetDC(hwnd);
  736.     if(hdc == NULL)
  737.         return LISTERR_CREATEFAILED;
  738.  
  739.     lpLI->hfontLB = MakeFont(hdc, lpLI->szFont, lpLI->iFontSize);
  740.  
  741.     if(lpLI->hfontLB)
  742.         hfontOld = SelectObject(hdc, lpLI->hfontLB);
  743.  
  744.     GetTextMetrics(hdc, &tm);
  745.  
  746.     if(hfontOld) 
  747.         SelectObject(hdc, hfontOld);
  748.  
  749.     ReleaseDC(hwnd, hdc);
  750.  
  751.     lpLI->iLineSpace = tm.tmHeight + tm.tmExternalLeading;
  752.  
  753.     // Set measurements of embedded pane. If author specified values,
  754.     // convert them from text measurements to pixel measurements.
  755.  
  756.     hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
  757.  
  758.     cxScreen = GetDeviceCaps(hdc, HORZRES);
  759.     cyScreen = GetDeviceCaps(hdc, VERTRES);
  760.  
  761.     DeleteDC(hdc);
  762.  
  763.     if(lpLI->iWidth == 0)
  764.     {
  765.         lpLI->iWidth = cx;
  766.     }
  767.     else
  768.     {
  769.         lx = (long)lpLI->iWidth * (long)cxScreen / (long)1024;
  770.         lpLI->iWidth = (UINT)lx;
  771.     }
  772.  
  773.     if(lpLI->iHeight == 0)
  774.     {
  775.         lpLI->iHeight = cy;
  776.     }
  777.     else
  778.     {
  779.         ly = (long)lpLI->iHeight * (long)cyScreen / (long)1024;
  780.         lpLI->iHeight = (UINT)ly;
  781.     }
  782.  
  783.     lpLI->iLines  = (lpLI->iHeight-BORDER_WIDTH*2) / lpLI->iLineSpace;
  784.     lpLI->iHeight = lpLI->iLines * lpLI->iLineSpace + BORDER_WIDTH * 2;
  785.  
  786.     // Set current selection & position values 
  787.  
  788.     lpLI->nTop = lpLI->nCurSel = 0;
  789.  
  790.     return 0;
  791. }
  792.  
  793. /*************************************************************************
  794.  * InitPane : This BIG function initializes all the information for the
  795.  *            embedded pane. It parses the author-data string and sets
  796.  *            appropriate values in the pane information structure. It also
  797.  *            creates the child window that displays the list and handles
  798.  *            scrolling logic.
  799.  *
  800.  * Returns: Zero on success or -1 on failure (passed to WM_CREATE return).
  801.  *
  802.  *************************************************************************/
  803.  
  804. int InitPane(
  805.     HWND     hwnd,          // Handle of new embedded pane window
  806.     LPEWDATA lpew,          // Embedded pane create info
  807.     LPLISTINFO FAR *lplpLI, // To receive pointer to list info structure
  808.     int     cx,             // Default sizes from LPCREATE 
  809.     int     cy)
  810. {
  811.     LPLISTINFO lpLI;        // Pane information structure
  812.  
  813.     int iRet = 0;
  814.  
  815.     *lplpLI = NULL;
  816.  
  817.     // Allocate pane information structure
  818.  
  819.     lpLI = (LPLISTINFO)GlobalAllocPtr(GMEM_MOVEABLE | GMEM_ZEROINIT, sizeof(LISTINFO));
  820.     if(lpLI == NULL)
  821.     {
  822.         iRet = LISTERR_MEMORY;
  823.         goto ReturnError;
  824.     }
  825.     
  826.     // Parse the author data string, read the list information from
  827.     // baggage, and initialize the display data for the pane.
  828.  
  829.     iRet = ParseAuthorString(lpLI, lpew->szAuthorData);
  830.     if(iRet)
  831.         goto ReturnError;
  832.  
  833.     iRet = ReadCmdList(lpew->szFileName, lpLI);
  834.     if(iRet)
  835.         goto ReturnError;
  836.  
  837.     iRet = InitPaneAspect(hwnd, lpLI, cx, cy);
  838.     if(iRet)
  839.         goto ReturnError;
  840.  
  841.     // If this is a display pane, create a child window to handle the
  842.     // scrolling interface. This window is not needed for panes created
  843.     // just for printing or copying.
  844.  
  845.     if(!(lpew->dwFlags & EWF_PRINT || lpew->dwFlags & EWF_COPY))
  846.     {
  847.         lpLI->hwndScroll = CreateWindow(szScrollClassName, NULL, 
  848.                     WS_CHILD | WS_BORDER,
  849.                     BORDER_WIDTH, 
  850.                     BORDER_WIDTH, 
  851.                     lpLI->iWidth -BORDER_WIDTH*2, 
  852.                     lpLI->iHeight-BORDER_WIDTH*2, 
  853.                     hwnd, NULL, ghModule, lpLI);
  854.     }
  855.  
  856.     lpLI->hwndPane = hwnd;
  857.  
  858.     *lplpLI = lpLI;
  859.  
  860.     return 0;
  861.  
  862. ReturnError:
  863.  
  864.     if(lpLI) GlobalFreePtr(lpLI);
  865.  
  866.     return iRet;
  867. }
  868.  
  869. /**************************************************************************
  870.  * LDLLHandler: Processes notification messages sent from Viewer to the
  871.  *              DLL. This one only processes initialization and termination
  872.  *              messages.
  873.  *
  874.  **************************************************************************/
  875.  
  876. LONG CALLBACK LDLLHandler(
  877.     UINT msg,                   // Message to process
  878.     LPARAM lParam1,             // Message parameter
  879.     LPARAM lParam2)             // Message parameter
  880. {
  881.     LPVWRINFO lpVwrInfo;
  882.  
  883.     switch(msg)
  884.     {
  885.     case DW_WHATMSG:
  886.         return DC_INITTERM;
  887.  
  888.     case DW_INIT:
  889.         lpVwrInfo = AddTask(LOWORD(lParam1));
  890.         if(lpVwrInfo == NULL)
  891.             return FALSE;
  892.  
  893.         lpVwrInfo->vwr = VwrFromHinst(LOWORD(lParam1));
  894.  
  895.         return TRUE;
  896.  
  897.     case DW_TERM:
  898.  
  899.         DeleteTask(LOWORD(lParam1));
  900.  
  901.         return TRUE;
  902.     }
  903. }
  904.  
  905.  
  906.  
  907.